package com.quanxiaoha.weblog.admin.config;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.quanxiaoha.weblog.admin.constant.RedisKeyConstants;
import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum;
import com.quanxiaoha.weblog.common.exception.BizException;
import com.quanxiaoha.weblog.common.utils.Response;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;

@Slf4j
/**
 * [Sa-Token 权限认证] 配置类
 */
@Configuration
public class SaTokenConfigure {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 注册 [Sa-Token全局过滤器]
     */
    @Bean
    public SaServletFilter getSaServletFilter() {
        return new SaServletFilter()
                // 拦截地址
                .addInclude("/admin/**")    /* 拦截全部path */
                // 鉴权方法：每次访问进入
                .setAuth(obj -> {
                    // 登录校验
                    SaRouter.match("/admin/**") // 拦截所有路由
                            .check(r -> StpUtil.checkLogin()); // 校验是否登录

                    // 文章模块
                    SaRouter.match("/admin/article/**")
                            .notMatch("/admin/article/list")
                            .notMatch("/admin/article/detail")
                            .check(r -> StpUtil.checkRole("ROLE_ADMIN"));
                    // 评论模块
                    SaRouter.match("/admin/comment/**")
                            .notMatch("/admin/comment/list")
                            .check(r -> StpUtil.checkRole("ROLE_ADMIN"));
                    // 知识库模块
                    SaRouter.match("/admin/wiki/**")
                            .notMatch("/admin/wiki/list")
                            .notMatch("/admin/catalog/list")
                            .check(r -> {
                                StpUtil.checkRole("ROLE_ADMIN");
                                log.info("用户访问知识库模块");
                            });

                })  
                // 异常处理方法
                .setError(e -> {
                    log.error("Sa-Token auth error: {}", e.getMessage());

                    // 根据异常类型，构造统一的 Response 响应体
                    Response<?> body;
                    if (e instanceof NotLoginException) {
                        body = Response.fail(ResponseCodeEnum.UNAUTHORIZED);
                    } else if (e instanceof NotRoleException || e instanceof NotPermissionException) {
                        body = Response.fail(ResponseCodeEnum.FORBIDDEN);
                    } else if (e instanceof BizException biz) {
                        body = Response.fail(biz);
                    } else {
                        body = Response.fail(ResponseCodeEnum.SYSTEM_ERROR);
                    }

                    // 设置返回头为 JSON，返回 JSON 字符串，避免被当作普通字符串输出
                    try {
                        SaHolder.getResponse().setHeader("Content-Type", "application/json;charset=UTF-8");
                        return new ObjectMapper().writeValueAsString(body);
                    } catch (Exception ex) {
                        // 兜底：序列化异常时，返回一个固定 JSON 字符串
                        return "{\"success\":false,\"message\":\"出错啦，后台小哥正在努力修复中...\",\"errorCode\":\"10000\",\"data\":null}";
                    }
                })

                ;
    }

}


